﻿using System;
using System.Collections.Generic;
using System.Text;

namespace NutriStat
{
    /// <summary>
    /// This class contains a static list of Unit objects represeting all the different
    /// units of measurement that NutriStat uses. Other objects will call the Unit objects
    /// of this method in order to ensure consistent use of abbrevations and names.
    /// </summary>
    public class MeasurementUnits 
    {
        public static Unit Millimeter = new Unit(SharedStrings.MILLIMETER, SharedStrings.MILLIMETERS_ABBR, "Millimeter (mm)", "metric");
        public static Unit Centimeter = new Unit(SharedStrings.CENTIMETER, SharedStrings.CENTIMETERS_ABBR, "Centimeter (cm)", "metric");
        public static Unit Inch = new Unit(SharedStrings.INCH, SharedStrings.INCHES_ABBR, "Inch (in)", "customary");
        public static Unit Pound = new Unit(SharedStrings.POUND, SharedStrings.POUNDS_ABBR, "Pound (lbs)", "customary");
        public static Unit Kilogram = new Unit(SharedStrings.KILOGRAM, SharedStrings.KILOGRAMS_ABBR, "Kilogram (kg)", "metric");
        public static Unit Year = new Unit("Year", "yrs", "Years (yrs)", string.Empty);
        public static Unit Month = new Unit("Month", "mos", "Months (mos)", string.Empty);
        public static Unit Day = new Unit("Day", "days", "Days", string.Empty);
    }

    /// <summary>
    /// Objects of this class represent a measurement unit. For example, millimeters, kilograms,
    /// inches, liters, etc. This is used to present uniform naming and abbrevation conventions
    /// across all parts of the application.
    /// </summary>
    public class Unit
    {
        #region Data
        #region Protected Data
        #endregion Protected Data

        #region Private Data
        private string name;
        private string abbreviation;
        private string fullName;
        private string system;
        #endregion Private Data;

        #region Internal Data
        #endregion Internal Data        
        #endregion Data

        #region Constructors
        /// <summary>
        /// The constructor for Unit object.
        /// </summary>
        /// <param name="abbreviation">The unit abbreviation to use.</param>
        /// <param name="fullName">The full name of the unit. This includes the name of the unit plus the abbreviation.</param>
        /// <param name="name">The name of the unit.</param>
        /// <param name="system">The measurement system to which the unit belongs. Typically metric or imperial/customary.</param>
        public Unit(string name, string abbreviation, string fullName, string system)
        {
            #region Input Validation
            #endregion Input Validation

            Name = name;
            Abbreviation = abbreviation;
            FullName = fullName;
            System = system;
        }
        #endregion Constructors

        #region Properties
        #region Public Properties
        /// <summary>
        /// Gets the name of the unit, e.g. "Kilogram" for kilograms.
        /// </summary>
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        /// <summary>
        /// Gets the abbreviation for the unit. E.g. "mm" for millimeters, "kg" for kilograms.
        /// </summary>
        public string Abbreviation
        {
            get
            {
                return abbreviation;
            }
            set
            {
                abbreviation = value;
            }
        }

        /// <summary>
        /// Gets the full name of the unit. E.g. "millimeters (mm)" - note the inclusion of the abbreviation.
        /// </summary>
        public string FullName
        {
            get
            {
                return fullName;
            }
            set
            {
                fullName = value;
            }
        }

        /// <summary>
        /// Gets the type of measurement system; typically imperial/customary or metric.
        /// </summary>
        public string System
        {
            get
            {
                return system;
            }
            set
            {
                system = value;
            }
        }
        #endregion Public Properties

        #region Protected Properties
        #endregion Protected Properties

        #region Private Properties
        #endregion Private Properties
        #endregion Properties

        #region Methods
        #region Public Methods
        /// <summary>
        /// The ToString() method for the Unit object. Returns the full name of the unit.
        /// </summary>
        /// <returns>string</returns>
        public override string ToString()
        {
            return FullName;
        }

        /// <summary>
        /// Converts a number from the current measurement type to inches.
        /// </summary>
        /// <returns>double</returns>
        public double ToInches()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Centimeter.Abbreviation))
                return 0.393700787;
            else if (this.Abbreviation.Equals(MeasurementUnits.Millimeter.Abbreviation))
                return 0.0393700787;
            else if (this.Abbreviation.Equals(MeasurementUnits.Inch.Abbreviation))
                return 1.00000000;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to centimeters.
        /// </summary>
        /// <returns>double</returns>
        public double ToCentimeters()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Centimeter.Abbreviation))
                return 1.00000000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Millimeter.Abbreviation))
                return 0.100000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Inch.Abbreviation))
                return 2.540000;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to millimeters.
        /// </summary>
        /// <returns>double</returns>
        public double ToMillimeters()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Centimeter.Abbreviation))
                return 10.0000000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Millimeter.Abbreviation))
                return 1.000000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Inch.Abbreviation))
                return 25.40000;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to pounds.
        /// </summary>
        /// <returns>double</returns>
        public double ToPounds()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Kilogram.Abbreviation))
                return 2.20462262;
            else if (this.Abbreviation.Equals(MeasurementUnits.Pound.Abbreviation))
                return 1.000000;
            else if (this.Abbreviation.Equals(SharedStrings.OUNCES_ABBR))
                return 0.0625;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to kilograms.
        /// </summary>
        /// <returns>double</returns>
        public double ToKilograms()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Kilogram.Abbreviation))
                return 1.000000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Pound.Abbreviation))
                return 0.45359237;
            else if (this.Abbreviation.Equals(SharedStrings.OUNCES_ABBR))
                return 0.0283495231;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to ounces.
        /// </summary>
        /// <returns>double</returns>
        public double ToOunces()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Kilogram.Abbreviation))
                return 35.2739619;
            else if (this.Abbreviation.Equals(MeasurementUnits.Pound.Abbreviation))
                return 16.00000;
            else if (this.Abbreviation.Equals(SharedStrings.OUNCES_ABBR))
                return 1.00000000;
            else
                return -1.00000000;
        }

        /// <summary>
        /// Converts a number from the current measurement type to months.
        /// </summary>
        /// <returns>double</returns>
        public double ToMonths()
        {
            if (this.Abbreviation.Equals(MeasurementUnits.Month.Abbreviation))
                return 1.0000;
            else if (this.Abbreviation.Equals(MeasurementUnits.Year.Abbreviation))
                return 12;
            else if (this.Abbreviation.Equals(MeasurementUnits.Day.Abbreviation))
                return 30.4375;
            else
                return -1.00000000;
        }
        #endregion Public Methods

        #region Protected Methods
        #endregion Protected Methods

        #region Private Methods
        #endregion Private Methods
        #endregion Methods
    }
}
